package com.ipan.poi.easyexcel;

import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.util.StringUtils;
import com.ipan.poi.easyexcel.ehcache2.SimpleReadCacheSelector2;
import com.ipan.poi.easyexcel.listener.SyncReadHeadListener;
import com.ipan.poi.easyexcel.listener.SyncReadLimitListener;
import com.ipan.poi.easyexcel.listener.SyncReadListener2;
import com.ipan.poi.easyexcel.patch305.EasyExcel2;
import com.ipan.poi.easyexcel.patch305.ExcelReader2;

/**
 * EasyExcel工具（ehcache2版）
 * EasyExcel2.read()时候，参数为文件是可以识别xls、xlsx、csv的，如果是文件流，则仅支持xls、xlsx；
 * EasyExcel_v3.0.5对csv文件读取后未释放资源，是bug；
 * 
 * @author iPan
 * @date 2022-01-25
 */
public class EasyExcelUtil2 {
	
	// --- 同步读取文件头部 --- //
	/**
	 * 仅读取文件标题行
	 * 
	 * @param filePath 文件路径
	 * @return 标题信息
	 */
	public static Map<Integer, String> syncReadHead(String filePath) {
		ExcelReader2 reader = EasyExcel2.read(filePath)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadHead(reader, null, null, null);
	}
	/**
	 * 仅读取文件标题行
	 * 
	 * @param filePath 文件路径
	 * @param headRowNumber 标题行位置（从1开始编号，标题行的下一行就是数据表格）
	 * @param sheetNo 表格位置
	 * @param sheetName 表格名称
	 * @return 标题信息
	 */
	public static Map<Integer, String> syncReadHead(String filePath, Integer headRowNumber, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(filePath)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadHead(reader, headRowNumber, sheetNo, sheetName);
	}
	
	private static Map<Integer, String> doSyncReadHead(ExcelReader2 reader, Integer headRowNumber, Integer sheetNo, String sheetName) {
		SyncReadHeadListener readHeadListener = new SyncReadHeadListener();
		ReadSheet readSheet = new ReadSheet();
        if (sheetNo != null && sheetNo > -1) {
        	readSheet.setSheetNo(sheetNo);
        }
        if (sheetName != null) {
        	readSheet.setSheetName(sheetName);
        }
        if (headRowNumber != null && headRowNumber > -1) {
        	readSheet.setHeadRowNumber(headRowNumber);
        }
        readSheet.getCustomReadListenerList().add(readHeadListener);
        reader.read(readSheet);
        reader.finish();
        return readHeadListener.getHeadMap();
	}

	public static Map<Integer, String> syncReadHead(File file) {
		ExcelReader2 reader = EasyExcel2.read(file)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadHead(reader, null, null, null);
	}
	public static Map<Integer, String> syncReadHead(File file, Integer headRowNumber, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(file)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadHead(reader, headRowNumber, sheetNo, sheetName);
	}
	
	public static Map<Integer, String> syncReadHead(InputStream inputStream) {
		ExcelReader2 reader = EasyExcel2.read(inputStream)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadHead(reader, null, null, null);
	}
	public static Map<Integer, String> syncReadHead(InputStream inputStream, Integer headRowNumber, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(inputStream)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadHead(reader, headRowNumber, sheetNo, sheetName);
	}
	
	// --- 同步读取前N行数据 --- //
	/**
	 * 仅读取文件标题行
	 * 
	 * @param filePath 文件路径
	 * @return 标题信息
	 */
	public static List<Map<Integer, String>> syncReadLimit(String filePath, int limit) {
		ExcelReader2 reader = EasyExcel2.read(filePath)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadLimit(reader, null, limit, null, null);
	}
	/**
	 * 仅读取文件标题行
	 * 
	 * @param filePath 文件路径
	 * @param headRowNumber 标题行位置（从1开始编号，标题行的下一行就是数据表格）
	 * @param limit 读前几行
	 * @param sheetNo 表格位置
	 * @param sheetName 表格名称
	 * @return 标题信息
	 */
	public static List<Map<Integer, String>> syncReadLimit(String filePath, Integer headRowNumber, int limit, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(filePath)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadLimit(reader, headRowNumber, limit, sheetNo, sheetName);
	}
	
	private static List<Map<Integer, String>> doSyncReadLimit(ExcelReader2 reader, Integer headRowNumber, int limit, Integer sheetNo, String sheetName) {
		SyncReadLimitListener readHeadListener = new SyncReadLimitListener(limit);
		ReadSheet readSheet = new ReadSheet();
        if (sheetNo != null && sheetNo > -1) {
        	readSheet.setSheetNo(sheetNo);
        }
        if (StringUtils.isNotBlank(sheetName)) {
        	readSheet.setSheetName(sheetName);
        }
        if (headRowNumber != null && headRowNumber > -1) {
        	readSheet.setHeadRowNumber(headRowNumber);
        }
        readSheet.getCustomReadListenerList().add(readHeadListener);
        reader.read(readSheet);
        reader.finish();
        return readHeadListener.getData();
	}
	
	public static List<Map<Integer, String>> syncReadLimit(File file, int limit) {
		ExcelReader2 reader = EasyExcel2.read(file)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadLimit(reader, null, limit, null, null);
	}
	public static List<Map<Integer, String>> syncReadLimit(File file, Integer headRowNumber, int limit, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(file)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadLimit(reader, headRowNumber, limit, sheetNo, sheetName);
	}
	
	public static List<Map<Integer, String>> syncReadLimit(InputStream inputStream, int limit) {
		ExcelReader2 reader = EasyExcel2.read(inputStream)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadLimit(reader, null, limit, null, null);
	}
	public static List<Map<Integer, String>> syncReadLimit(InputStream inputStream, Integer headRowNumber, int limit, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(inputStream)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncReadLimit(reader, headRowNumber, limit, sheetNo, sheetName);
	}
	
	//-- 同步读取整个文档 --//
	/**
	 * 读取整个文件
	 * 
	 * @param filePath 文件路径
	 * @return 文件列表
	 */
	public static List<Map<Integer, String>> syncRead(String filePath) {
		ExcelReader2 reader = EasyExcel2.read(filePath)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncRead(reader, null, null, null, true);
	}
	/**
	 * 读取整个文件
	 * 
	 * @param filePath 文件路径
	 * @param headRowNumber 标题行位置（从1开始编号，标题行的下一行就是数据表格）
	 * @param sheetNo 表格位置
	 * @param sheetName 表格名称
	 * @return 文件列表
	 */
	public static List<Map<Integer, String>> syncRead(String filePath, Integer headRowNumber, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(filePath)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncRead(reader, headRowNumber, sheetNo, sheetName, true);
	}
	public static List<Map<Integer, String>> syncRead(File file) {
		ExcelReader2 reader = EasyExcel2.read(file)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncRead(reader, null, null, null, true);
	}
	public static List<Map<Integer, String>> syncRead(File file, Integer headRowNumber, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(file)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncRead(reader, headRowNumber, sheetNo, sheetName, true);
	}
	
	public static List<Map<Integer, String>> syncRead(InputStream inputStream) {
		ExcelReader2 reader = EasyExcel2.read(inputStream)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncRead(reader, null, null, null, true);
	}
	public static List<Map<Integer, String>> syncRead(InputStream inputStream, Integer headRowNumber, Integer sheetNo, String sheetName) {
		ExcelReader2 reader = EasyExcel2.read(inputStream)
				.readCacheSelector(new SimpleReadCacheSelector2())
				.build();
		return doSyncRead(reader, headRowNumber, sheetNo, sheetName, true);
	}
	private static List<Map<Integer, String>> doSyncRead(ExcelReader2 reader, Integer headRowNumber, Integer sheetNo, String sheetName, boolean ignoreEmptyRow) {
		SyncReadListener2 readListener = new SyncReadListener2(ignoreEmptyRow);
		ReadSheet readSheet = new ReadSheet();
        if (sheetNo != null && sheetNo > -1) {
        	readSheet.setSheetNo(sheetNo);
        }
        if (StringUtils.isNotBlank(sheetName)) {
        	readSheet.setSheetName(sheetName);
        }
        if (headRowNumber != null && headRowNumber > -1) {
        	readSheet.setHeadRowNumber(headRowNumber);
        }
        readSheet.getCustomReadListenerList().add(readListener);
        reader.read(readSheet);
        reader.finish();
        return readListener.getList();
	}
	
	public static void main(String[] args) {
//		System.out.println(syncReadHead("C:/bigfile_test/khtestOne.xlsx"));
//		System.out.println(syncReadHead("C:/bigfile_test/khtestOne_testhead.xlsx", 4, 0, null));
//		System.out.println(syncReadHead("C:/bigfile_test/khtestOne_testhead.xlsx", 4, null, "sheet1"));
//		System.out.println(syncReadHead(new File("C:/bigfile_test/khtestOne.xlsx")));
//		syncReadLimit("C:/bigfile_test/file2.xlsx", 3).forEach(item -> System.out.println(item));
//		syncReadLimit("C:/bigfile_test/khtestOne_testhead.xlsx", 4, 1, 0, null).forEach(item -> System.out.println(item));
//		syncReadLimit("C:/bigfile_test/khtestOne_testhead.xlsx", 4, 1, null, "sheet1").forEach(item -> System.out.println(item));
//		System.out.println(syncReadHead("C:/bigfile_test/dataType.csv"));
//		System.out.println(syncReadHead("C:/bigfile_test/file1.csv", 4, 0, null));
//		syncReadLimit("C:/bigfile_test/file1.csv", 4, 3, 0, null).forEach(item -> System.out.println(item));
//		System.out.println();
		List<Map<Integer, String>> list = syncRead(new File("d:/user.xlsx"));
		for (Map<Integer, String> item : list) {
			System.out.println(item);
		}
	}
	
}
